package com.pai4j.zwiki.service.template;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 论文图表管理器
 * 管理论文中图表的插入、排版、编号和引用
 *
 * @author pai4j
 * @since 2025-10-12
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ThesisDiagramManager {

    // 图表类型到中文名称的映射
    private static final Map<String, String> DIAGRAM_TYPE_NAMES = new HashMap<>();
    
    static {
        DIAGRAM_TYPE_NAMES.put("classDiagram", "类图");
        DIAGRAM_TYPE_NAMES.put("packageDependency", "包依赖图");
        DIAGRAM_TYPE_NAMES.put("sequenceDiagram", "时序图");
        DIAGRAM_TYPE_NAMES.put("layerArchitecture", "分层架构图");
        DIAGRAM_TYPE_NAMES.put("componentInteraction", "组件交互图");
        DIAGRAM_TYPE_NAMES.put("moduleRelation", "模块关系图");
        DIAGRAM_TYPE_NAMES.put("businessFlow", "业务流程图");
        DIAGRAM_TYPE_NAMES.put("stateMachine", "状态机图");
        DIAGRAM_TYPE_NAMES.put("designPatterns", "设计模式图");
        DIAGRAM_TYPE_NAMES.put("deploymentArchitecture", "部署架构图");
        DIAGRAM_TYPE_NAMES.put("monitoringArchitecture", "监控架构图");
        DIAGRAM_TYPE_NAMES.put("erDiagram", "ER图");
        DIAGRAM_TYPE_NAMES.put("tableStructure", "表结构图");
    }

    // 图表类型到建议章节的映射
    private static final Map<String, List<String>> DIAGRAM_CHAPTER_MAPPING = new HashMap<>();
    
    static {
        DIAGRAM_CHAPTER_MAPPING.put("classDiagram", Arrays.asList("系统设计", "详细设计", "代码结构"));
        DIAGRAM_CHAPTER_MAPPING.put("packageDependency", Arrays.asList("系统设计", "架构设计"));
        DIAGRAM_CHAPTER_MAPPING.put("sequenceDiagram", Arrays.asList("系统设计", "交互设计", "业务流程"));
        DIAGRAM_CHAPTER_MAPPING.put("layerArchitecture", Arrays.asList("系统架构", "架构设计", "总体设计"));
        DIAGRAM_CHAPTER_MAPPING.put("componentInteraction", Arrays.asList("系统架构", "架构设计"));
        DIAGRAM_CHAPTER_MAPPING.put("moduleRelation", Arrays.asList("系统架构", "模块设计"));
        DIAGRAM_CHAPTER_MAPPING.put("businessFlow", Arrays.asList("业务流程", "系统设计", "需求分析"));
        DIAGRAM_CHAPTER_MAPPING.put("stateMachine", Arrays.asList("详细设计", "状态设计"));
        DIAGRAM_CHAPTER_MAPPING.put("designPatterns", Arrays.asList("详细设计", "设计模式", "技术选型"));
        DIAGRAM_CHAPTER_MAPPING.put("deploymentArchitecture", Arrays.asList("系统部署", "部署方案"));
        DIAGRAM_CHAPTER_MAPPING.put("monitoringArchitecture", Arrays.asList("运维方案", "监控设计"));
        DIAGRAM_CHAPTER_MAPPING.put("erDiagram", Arrays.asList("数据库设计", "数据模型"));
        DIAGRAM_CHAPTER_MAPPING.put("tableStructure", Arrays.asList("数据库设计", "表结构设计"));
    }

    /**
     * 智能插入图表到论文内容中
     *
     * @param thesisContent 论文内容
     * @param availableDiagrams 可用的图表（类型 -> 文件路径）
     * @return 插入图表后的论文内容
     */
    public String intelligentlyInsertDiagrams(String thesisContent, Map<String, String> availableDiagrams) {
        log.info("开始智能插入图表，可用图表数量: {}", availableDiagrams.size());

        // 解析论文结构
        List<ChapterInfo> chapters = parseChapters(thesisContent);
        
        // 为每个章节匹配合适的图表
        Map<String, List<DiagramInsertInfo>> chapterDiagrams = matchDiagramsToChapters(chapters, availableDiagrams);
        
        // 插入图表到论文中
        String result = insertDiagramsIntoContent(thesisContent, chapterDiagrams);
        
        // 添加图表目录
        result = addDiagramIndex(result, chapterDiagrams);
        
        log.info("图表插入完成");
        return result;
    }

    /**
     * 为章节匹配合适的图表
     */
    private Map<String, List<DiagramInsertInfo>> matchDiagramsToChapters(
            List<ChapterInfo> chapters, 
            Map<String, String> availableDiagrams) {
        
        Map<String, List<DiagramInsertInfo>> result = new LinkedHashMap<>();
        int figureNumber = 1; // 图表编号计数器

        for (ChapterInfo chapter : chapters) {
            List<DiagramInsertInfo> diagrams = new ArrayList<>();
            
            // 为每个图表类型检查是否适合当前章节
            for (Map.Entry<String, String> diagram : availableDiagrams.entrySet()) {
                String diagramType = diagram.getKey();
                String diagramPath = diagram.getValue();
                
                if (isDiagramSuitableForChapter(diagramType, chapter.getTitle())) {
                    DiagramInsertInfo insertInfo = new DiagramInsertInfo();
                    insertInfo.setDiagramType(diagramType);
                    insertInfo.setDiagramPath(diagramPath);
                    insertInfo.setFigureNumber(figureNumber++);
                    insertInfo.setCaption(generateCaption(diagramType, chapter.getTitle()));
                    insertInfo.setDescription(generateDescription(diagramType));
                    
                    diagrams.add(insertInfo);
                }
            }
            
            if (!diagrams.isEmpty()) {
                result.put(chapter.getTitle(), diagrams);
            }
        }

        return result;
    }

    /**
     * 判断图表是否适合某个章节
     */
    private boolean isDiagramSuitableForChapter(String diagramType, String chapterTitle) {
        List<String> suitableChapters = DIAGRAM_CHAPTER_MAPPING.get(diagramType);
        if (suitableChapters == null) {
            return false;
        }

        for (String suitable : suitableChapters) {
            if (chapterTitle.contains(suitable)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 生成图表标题
     */
    private String generateCaption(String diagramType, String chapterTitle) {
        String typeName = DIAGRAM_TYPE_NAMES.getOrDefault(diagramType, "系统图");
        return typeName;
    }

    /**
     * 生成图表描述
     */
    private String generateDescription(String diagramType) {
        return switch (diagramType) {
            case "classDiagram" -> "图中展示了系统的核心类结构，包括类之间的继承和依赖关系，" +
                    "体现了面向对象的设计思想。";
            case "packageDependency" -> "图中展示了各个包之间的依赖关系，反映了系统的模块化设计和分层思想。";
            case "sequenceDiagram" -> "图中展示了系统的主要业务流程和组件间的交互时序，" +
                    "清晰地描述了请求的处理流程。";
            case "layerArchitecture" -> "图中展示了系统的分层架构设计，各层职责明确，实现了高内聚低耦合。";
            case "componentInteraction" -> "图中展示了系统各组件之间的交互关系，包括前端、后端、数据库等组件的协作方式。";
            case "moduleRelation" -> "图中展示了系统的模块划分和模块间的关系，体现了系统的模块化设计。";
            case "businessFlow" -> "图中展示了系统的核心业务流程，包括各个处理步骤和分支判断。";
            case "stateMachine" -> "图中展示了对象的状态转换过程，清晰地描述了状态变化的条件和触发事件。";
            case "designPatterns" -> "图中展示了系统中应用的设计模式，体现了良好的软件设计实践。";
            case "deploymentArchitecture" -> "图中展示了系统的部署架构，包括服务器、数据库、缓存等组件的部署方式。";
            case "monitoringArchitecture" -> "图中展示了系统的监控架构，包括日志收集、指标监控、链路追踪等监控体系。";
            case "erDiagram" -> "图中展示了系统的数据库ER模型，描述了实体、属性和实体间的关系。";
            case "tableStructure" -> "图中展示了数据库表的详细结构，包括字段名称、类型、约束等信息。";
            default -> "该图展示了系统的相关设计内容。";
        };
    }

    /**
     * 将图表插入到论文内容中
     */
    private String insertDiagramsIntoContent(
            String content, 
            Map<String, List<DiagramInsertInfo>> chapterDiagrams) {
        
        StringBuilder result = new StringBuilder();
        String[] paragraphs = content.split("\n\n");

        for (String paragraph : paragraphs) {
            result.append(paragraph).append("\n\n");

            // 检查是否是章节标题
            for (Map.Entry<String, List<DiagramInsertInfo>> entry : chapterDiagrams.entrySet()) {
                String chapterTitle = entry.getKey();
                
                if (paragraph.contains(chapterTitle)) {
                    // 在章节后插入图表
                    for (DiagramInsertInfo diagram : entry.getValue()) {
                        result.append(formatDiagramInsertion(diagram));
                    }
                }
            }
        }

        return result.toString();
    }

    /**
     * 格式化图表插入内容
     */
    private String formatDiagramInsertion(DiagramInsertInfo diagram) {
        StringBuilder sb = new StringBuilder();
        
        // 添加图表引用标记
        sb.append(String.format("<img src=\"%s\" alt=\"图%d %s\" style=\"width:100%%;max-width:800px;\" />\n\n",
                diagram.getDiagramPath(),
                diagram.getFigureNumber(),
                diagram.getCaption()));
        
        // 添加图表说明
        sb.append(String.format("<div class=\"figure-caption\">图%d %s</div>\n\n",
                diagram.getFigureNumber(),
                diagram.getCaption()));
        
        // 添加图表描述
        sb.append(String.format("<div class=\"figure-description\">%s</div>\n\n",
                diagram.getDescription()));
        
        return sb.toString();
    }

    /**
     * 添加图表目录
     */
    private String addDiagramIndex(String content, Map<String, List<DiagramInsertInfo>> chapterDiagrams) {
        if (chapterDiagrams.isEmpty()) {
            return content;
        }

        StringBuilder index = new StringBuilder();
        index.append("\n\n## 图表目录\n\n");

        for (Map.Entry<String, List<DiagramInsertInfo>> entry : chapterDiagrams.entrySet()) {
            for (DiagramInsertInfo diagram : entry.getValue()) {
                index.append(String.format("图%d %s\n",
                        diagram.getFigureNumber(),
                        diagram.getCaption()));
            }
        }

        index.append("\n\n");

        // 在摘要后、第一章前插入图表目录
        Pattern pattern = Pattern.compile("(#+\\s*摘要.*?)(\n\n)(#+\\s*第[一1]章)", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(content);
        
        if (matcher.find()) {
            return matcher.replaceFirst("$1$2" + index.toString() + "$3");
        }

        // 如果找不到合适位置，插入到开头
        return index.toString() + content;
    }

    /**
     * 解析章节信息
     */
    private List<ChapterInfo> parseChapters(String content) {
        List<ChapterInfo> chapters = new ArrayList<>();
        
        // 匹配章节标题（支持多种格式）
        Pattern chapterPattern = Pattern.compile("^(#+|第[一二三四五六七八九十\\d]+章)\\s+(.+)$", Pattern.MULTILINE);
        Matcher matcher = chapterPattern.matcher(content);

        while (matcher.find()) {
            ChapterInfo chapter = new ChapterInfo();
            chapter.setLevel(matcher.group(1).startsWith("#") ? matcher.group(1).length() : 1);
            chapter.setTitle(matcher.group(2).trim());
            chapter.setStartPosition(matcher.start());
            
            chapters.add(chapter);
        }

        return chapters;
    }

    /**
     * 生成图表插入建议
     *
     * @param chapterContent 章节内容
     * @param availableDiagrams 可用图表
     * @return 插入建议列表
     */
    public List<DiagramSuggestion> generateInsertionSuggestions(
            String chapterContent,
            Map<String, String> availableDiagrams) {
        
        List<DiagramSuggestion> suggestions = new ArrayList<>();

        for (Map.Entry<String, String> entry : availableDiagrams.entrySet()) {
            String diagramType = entry.getKey();
            String diagramPath = entry.getValue();

            // 分析章节内容，找到合适的插入位置
            int insertPosition = findBestInsertPosition(chapterContent, diagramType);
            
            if (insertPosition >= 0) {
                DiagramSuggestion suggestion = new DiagramSuggestion();
                suggestion.setDiagramType(diagramType);
                suggestion.setDiagramPath(diagramPath);
                suggestion.setInsertPosition(insertPosition);
                suggestion.setReason(generateInsertionReason(diagramType, chapterContent));
                suggestion.setConfidence(calculateConfidence(diagramType, chapterContent));
                
                suggestions.add(suggestion);
            }
        }

        // 按置信度排序
        suggestions.sort((a, b) -> Double.compare(b.getConfidence(), a.getConfidence()));

        return suggestions;
    }

    /**
     * 找到最佳插入位置
     */
    private int findBestInsertPosition(String content, String diagramType) {
        List<String> keywords = getKeywordsForDiagram(diagramType);
        
        for (String keyword : keywords) {
            int position = content.indexOf(keyword);
            if (position >= 0) {
                // 找到段落结束位置
                int endOfParagraph = content.indexOf("\n\n", position);
                return endOfParagraph >= 0 ? endOfParagraph : position;
            }
        }

        return -1;
    }

    /**
     * 获取图表相关的关键词
     */
    private List<String> getKeywordsForDiagram(String diagramType) {
        return switch (diagramType) {
            case "classDiagram" -> Arrays.asList("类设计", "类结构", "代码结构", "面向对象");
            case "layerArchitecture" -> Arrays.asList("架构设计", "分层设计", "系统架构", "架构模式");
            case "sequenceDiagram" -> Arrays.asList("业务流程", "交互流程", "处理流程", "调用流程");
            case "erDiagram" -> Arrays.asList("数据库设计", "数据模型", "ER模型", "实体关系");
            case "deploymentArchitecture" -> Arrays.asList("部署架构", "部署方案", "系统部署");
            default -> new ArrayList<>();
        };
    }

    /**
     * 生成插入理由
     */
    private String generateInsertionReason(String diagramType, String content) {
        return String.format("在此处插入%s可以更好地说明%s的设计思路",
                DIAGRAM_TYPE_NAMES.get(diagramType),
                extractMainTopic(content));
    }

    /**
     * 提取主要话题
     */
    private String extractMainTopic(String content) {
        if (content.contains("架构")) return "系统架构";
        if (content.contains("设计")) return "系统设计";
        if (content.contains("数据库")) return "数据库设计";
        if (content.contains("业务")) return "业务流程";
        return "系统实现";
    }

    /**
     * 计算置信度
     */
    private double calculateConfidence(String diagramType, String content) {
        List<String> keywords = getKeywordsForDiagram(diagramType);
        int matchCount = 0;

        for (String keyword : keywords) {
            if (content.contains(keyword)) {
                matchCount++;
            }
        }

        return keywords.isEmpty() ? 0.0 : (double) matchCount / keywords.size();
    }

    /**
     * 验证图表文件是否存在
     */
    public boolean validateDiagramFiles(Map<String, String> diagrams) {
        for (Map.Entry<String, String> entry : diagrams.entrySet()) {
            String diagramPath = entry.getValue();
            if (diagramPath == null || !Files.exists(Paths.get(diagramPath))) {
                log.warn("图表文件不存在: {} -> {}", entry.getKey(), diagramPath);
                return false;
            }
        }
        return true;
    }

    /**
     * 复制图表文件到论文目录
     */
    public Map<String, String> copyDiagramsToThesisDirectory(
            String taskId,
            Map<String, String> diagrams,
            String targetDir) throws IOException {
        
        Map<String, String> copiedDiagrams = new HashMap<>();
        Path targetPath = Paths.get(targetDir);
        Files.createDirectories(targetPath);

        for (Map.Entry<String, String> entry : diagrams.entrySet()) {
            String diagramType = entry.getKey();
            String sourcePath = entry.getValue();
            
            if (sourcePath != null && Files.exists(Paths.get(sourcePath))) {
                Path source = Paths.get(sourcePath);
                Path target = targetPath.resolve(diagramType + ".png");
                
                Files.copy(source, target);
                copiedDiagrams.put(diagramType, target.toString());
                
                log.info("复制图表: {} -> {}", source, target);
            }
        }

        return copiedDiagrams;
    }

    // ========== 内部类 ==========

    @Data
    public static class ChapterInfo {
        private int level;
        private String title;
        private int startPosition;
    }

    @Data
    public static class DiagramInsertInfo {
        private String diagramType;
        private String diagramPath;
        private int figureNumber;
        private String caption;
        private String description;
    }

    @Data
    public static class DiagramSuggestion {
        private String diagramType;
        private String diagramPath;
        private int insertPosition;
        private String reason;
        private double confidence;
    }
}

